package com.hyt.it.ogt.kq.service.gov.service.impl;


import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.enums.TaskKsConfigCode;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.feign.ks.model.PushExamConfigParam;
import com.hyt.it.ogt.kq.service.gov.mapper.TaskKsConfigMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.Task;
import com.hyt.it.ogt.kq.service.gov.model.entity.TaskKsConfig;
import com.hyt.it.ogt.kq.service.gov.model.param.TaskOnLineConfig;
import com.hyt.it.ogt.kq.service.gov.service.IOfficeTaskKsConfigService;
import com.hyt.it.ogt.kq.service.gov.service.ITaskKsConfigService;
import com.hyt.it.ogt.kq.service.gov.service.ITimeRoomCandidateService;
import com.hyt.it.ogt.kq.service.gov.service.ITimeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 配置表 服务实现类
 * </p>
 *
 * @author huangyh
 * @since 2021-11-24
 */
@Service
@Slf4j
public class TaskKsConfigServiceImpl extends BaseServiceImpl<TaskKsConfigMapper, TaskKsConfig> implements ITaskKsConfigService {

    @Resource
    private ITimeService iTimeService;

    @Resource
    private IOfficeTaskKsConfigService iOfficeTaskKsConfigService;

    @Resource
    private ITimeRoomCandidateService iTimeRoomCandidateService;

    @Override
    public List<PushExamConfigParam> getExamConfig(String taskId) {
        List<PushExamConfigParam> examConfigs = new ArrayList<>();

        List<TaskKsConfig> list = this.lambdaQuery()
                .eq(TaskKsConfig::getTaskId,taskId)
                .eq(TaskKsConfig::getDelFlag,false)
                .list();
        list.stream().forEach(taskKsConfig -> {
            PushExamConfigParam examConfig = new PushExamConfigParam();
            BeanUtils.copyProperties(taskKsConfig,examConfig);
            examConfigs.add(examConfig);
        });

        return examConfigs;
    }

    @Override
    public List<PushExamConfigParam> getExamConfigNoFalse(String taskId) {
        List<PushExamConfigParam> examConfigs = new ArrayList<>();
        List<TaskKsConfig> list = this.lambdaQuery()
                .eq(TaskKsConfig::getTaskId,taskId)
                .eq(TaskKsConfig::getDelFlag,false)
                .list();
        
        list.stream().forEach(taskKsConfig -> {
            if ("checkbox".equals(taskKsConfig.getConfigAttribute()) && "false".equals(taskKsConfig.getConfigValue())) {
                return ;
            }

            PushExamConfigParam examConfig = new PushExamConfigParam();
            BeanUtils.copyProperties(taskKsConfig, examConfig);
            examConfigs.add(examConfig);

        });
        // 需要过滤掉相同configCode的数据
        Map<String, PushExamConfigParam> coonfigCodeMap = new HashMap<>();
        for (Iterator<PushExamConfigParam> iterator = examConfigs.iterator(); iterator.hasNext();) {
            PushExamConfigParam pushExamConfigParamTemp =  iterator.next();
            if(coonfigCodeMap.containsKey(pushExamConfigParamTemp.getConfigCode())) {
                iterator.remove();
            }
            coonfigCodeMap.put(pushExamConfigParamTemp.getConfigCode(), pushExamConfigParamTemp);
        }
        return examConfigs;
    }

    @Override
    public void initTaskKsConfig(String taskId, String officeId) {

        Integer count = lambdaQuery()
                .eq(TaskKsConfig::getTaskId,taskId)
                .eq(TaskKsConfig::getDelFlag,false)
                .count();
        if (count <= 0) {
            //初始化机构参数
            iOfficeTaskKsConfigService.initOfficeKsConfig(officeId);

            //初始化任务参数
            baseMapper.initTaskKsConfig(taskId, officeId);

        }
    }

    @Override
    public List<TaskOnLineConfig> getTaskOnLineConfigByTaskId(String taskId) {

        List<TaskKsConfig> taskKsConfigs = this.lambdaQuery()
                .eq(TaskKsConfig::getTaskId, taskId)
                .eq(TaskKsConfig::getDelFlag, false)
                .select(TaskKsConfig::getConfigCode,
                        TaskKsConfig::getConfigAttribute, TaskKsConfig::getConfigGroup, TaskKsConfig::getConfigName,
                        TaskKsConfig::getConfigType, TaskKsConfig::getConfigValue, TaskKsConfig::getIconClass,
                        TaskKsConfig::getTaskId,TaskKsConfig::getId)
                .list();

        List<TaskOnLineConfig> taskOnLineConfigs = new ArrayList<>();
        taskKsConfigs.stream().forEach(taskKsConfig -> {
            TaskOnLineConfig taskOnLineConfig = new TaskOnLineConfig();
            BeanUtils.copyProperties(taskKsConfig,taskOnLineConfig);

            taskOnLineConfigs.add(taskOnLineConfig);
        });
        // 需要过滤掉相同configCode的数据
        Map<String, TaskOnLineConfig> coonfigCodeMap = new HashMap<>();
        for (Iterator<TaskOnLineConfig> iterator = taskOnLineConfigs.iterator(); iterator.hasNext();) {
            TaskOnLineConfig pushExamConfigParamTemp =  iterator.next();
            if(coonfigCodeMap.containsKey(pushExamConfigParamTemp.getConfigCode())) {
                iterator.remove();
            }
            coonfigCodeMap.put(pushExamConfigParamTemp.getConfigCode(), pushExamConfigParamTemp);
        }
        return taskOnLineConfigs;
    }

    @Override
    public void copyTaskKsConfig(String newTaskId, String oldTaskId, String userName) {

        baseMapper.copyTaskKsConfig(newTaskId, oldTaskId, userName);
    }

    @Override
    public void validExamConfig(Task task, List<TaskOnLineConfig> configList, int operateType) {

        Map<String, String> taskKsConfigMap = new HashMap<>();
        configList.stream().forEach(taskOnLineConfig -> {
            taskKsConfigMap.put(taskOnLineConfig.getConfigCode(),taskOnLineConfig.getConfigValue());
        });

        //是
        String on = TaskKsConfigCode.EXAM_CONFIG_CODE_ON.getCode();
        //否
        String off = TaskKsConfigCode.EXAM_CONFIG_CODE_OFF.getCode();

        List<String> errMsgList = new ArrayList<>();
        // 1.编辑时校验
        if(operateType == 2) {

            boolean timeCrossDayFlag = iTimeService.isTimeCrossDay(task.getId());
            // 提前登陆  检测所有批次不能夸天
            if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EARLYLOGON.getCode())) && timeCrossDayFlag) {
                errMsgList.add("任务下存在跨天的批次，不能开启'提前登录'；");
            }
            // 限制迟到  检测所有批次不能夸天
            if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_DELAYLOGON.getCode()))  && timeCrossDayFlag) {
                errMsgList.add("任务下存在跨天的批次，不能开启'限制迟到'；");
            }
            // 统一开考  检测所有批次不能夸天
            if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_UNIFIEDSTARTEND.getCode()))  && timeCrossDayFlag) {
                errMsgList.add("任务下存在跨天的批次，不能开启'统一开考,统一结束'；");
            }
        }

        // 2.公共校验
        // ====提前登录=======
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EARLYLOGON.getCode()))) {
            String loginMin = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EARLYLOGONMINS.getCode());
            if(null == loginMin || !NumberUtil.isInteger(loginMin) || NumberUtil.parseInt(loginMin) <= 0) {
                errMsgList.add("开启'提前登录'，'提前登录分钟数'必须设置且大于零的正整数；");
            }
        }
        // ====提前登录=======

        // ====限制迟到=======
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_DELAYLOGON.getCode()))) {
            String lateMin = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_DELAYLOGONMINS.getCode());
            if(null == lateMin || !NumberUtil.isInteger(lateMin) || NumberUtil.parseInt(lateMin) <= 0) {
                errMsgList.add("开启'限制迟到'，'限制迟到分钟数'必须设置且大于零的正整数；");
            }
        }
        // ====限制迟到=======

        // ====切换屏幕=======
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_OVERSCREEN.getCode()))) {
            String overTime = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_OVERSCREENLEAVETIME.getCode());
            if(null == overTime || !NumberUtil.isInteger(overTime) || NumberUtil.parseInt(overTime) <= 0) {
                errMsgList.add("开启'切换屏幕'，'限制切换分钟数'必须设置且大于零的正整数；");
            }
            String overCount = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_OVERSCREENNUMBER.getCode());
            if(null == overCount || !NumberUtil.isInteger(overCount) || NumberUtil.parseInt(overCount) <= 0) {
                errMsgList.add("开启'切换屏幕'，'限制切换次数'必须设置且大于零的正整数；");
            }
        }
        // ====切换屏幕=======
        // ===== “网页版考试、云考试客户端、手机网页考试、云考试app至少勾选一项” =====
        if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAMCLIENT.getCode()))
                && off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAMWEB.getCode()))
                && off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAM_MOBILE.getCode()))
                && off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAM_APP.getCode()))
        ) {
            errMsgList.add("至少勾选'网页版考试'、'云考试客户端'、'手机网页考试'、'云考试APP'一项");
        }
//        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAMCLIENT.getCode())) &&
//                on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAMWEB.getCode()))) {
//            errMsgList.add("'网页版考试'或'云考试客户端'只能勾选一项配置；");
//        }
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_EXAMCLIENT.getCode())) &&
                on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_SCREENSHOT.getCode()))) {
            //频率范围：0-12
            String shotTime = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_SCREENSHOTTIME.getCode());
            if (StringUtils.isBlank(shotTime) || Integer.parseInt(shotTime) < 0 || Integer.parseInt(shotTime) > 12) {
                errMsgList.add("云考试客户端，屏幕抓拍频率要设置在 0-12 范围内；");
            }
        }

        // ===== “网页版考试”或“云考试客户端” =====
        // ====锁定考试=======
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_LOCKEXAM.getCode()))) {
            String loginCount = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_LOGINCOUNT.getCode());
            if(null == loginCount || !NumberUtil.isInteger(loginCount) || NumberUtil.parseInt(loginCount) <= 0) {
                errMsgList.add("开启'锁定考试'，'允许登录次数'必须设置且大于零的正整数；");
            }
        }
        // ====锁定考试=======
        // ====分数线=======
        if (on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_SCOREGRADE.getCode()))) {
            //大于0，且允许2位小数
            String passScore = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_PASSSCORE.getCode());
            if (NumberUtil.isInteger(passScore)) {
                //是整数
                int integer = NumberUtil.parseInt(passScore);
                if (integer <= 0) {
                    errMsgList.add("开启'分数线'，'合格分数'不能小于或等于0");
                }
            } else {
                //是小数
                //获取小数点后的数字
                String decimal = StrUtil.subAfter(passScore, ".", true);
                //判断小数位数是否正确
                if (decimal.length() > 2) {
                    errMsgList.add("开启'分数线'，'合格分数'小数点后位数不能大于2位；");
                }
                //判断整数是否正确
                int integer = NumberUtil.parseInt(passScore);
                if (integer < 0) {
                    errMsgList.add("开启'分数线'，'合格分数'不能小于或等于0");
                }
            }
        }
        // ====分数线=======
        // ====乱序设置=======
        boolean disOrderFlag = on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_DISORDERSET.getCode()));
        if(disOrderFlag) {
            if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_QUESTIONSDISORDERSET.getCode())) &&
                   off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_OPTIONSDISORDERSET.getCode())) &&
                    off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_TOPIC_DISORDER.getCode()))) {
                errMsgList.add("开启'乱序设置'，'试题乱序设置'或'选项乱序设置'至少勾选一项配置；");
            }
        }
        boolean f = (on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_QUESTIONSDISORDERSET.getCode())) ||
                on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_OPTIONSDISORDERSET.getCode())) ||
                on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_TOPIC_DISORDER.getCode()))) &&
                !disOrderFlag;
        if(f) {
            errMsgList.add("勾选'试题乱序设置'或'选项乱序设置'，必须要开启'乱序设置'；");
        }
        // ====乱序设置=======
        // ===== 视频监控 ==begin===
        // 是否开启视频监控
        boolean videoMonitorFlag = on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOMONITORING.getCode()));
        if(videoMonitorFlag) {
            String catchPhotoPerTime = taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOSHOTSMINS.getCode());
            if(null == catchPhotoPerTime || !NumberUtil.isInteger(catchPhotoPerTime) || NumberUtil.parseInt(catchPhotoPerTime) <= 0) {
                errMsgList.add("开启'视频监控'，'照片抓拍间隔分钟数'必须设置且大于零的正整数；");
            }
        }
        // 是否开启双监控
        boolean dualMonitorFlag = on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_DUALMONITORING.getCode()));
        // 开启双监控
        if(dualMonitorFlag) {
            if(!videoMonitorFlag) {
                errMsgList.add("开启'双机位监控'，必须要开启'视频监控'；");
            }

        }
        // 是否人开启脸比对
        boolean faceCompareFlag = on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_FACECONTRAST.getCode()));
        if(faceCompareFlag) {
            if(!dualMonitorFlag) {
                errMsgList.add("开启'人脸比对'，必须要开启'双机位监控'；");
            }
            // 移动端照片未勾选
            if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_APPPHOTO.getCode()))) {
                errMsgList.add("开启'人脸比对'，必须勾选'移动端照片'；");
            }
            if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_ENROLLPHOTO.getCode())) &&
                    off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_AUTHENTICATIONPHOTO.getCode())) &&
                            off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_LOGONPCPHOTO.getCode()))) {
                errMsgList.add("开启'人脸比对'，必须同时勾选'移动端照片'和至少1个照片对比项；");
            }
            // 勾选了身份验证照片
            if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_AUTHENTICATIONPHOTO.getCode())) &&
                    off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_AUTHENTICATION.getCode()))) {
                errMsgList.add("勾选'身份验证照片'，必须勾选'身份验证'配置项；");
            }
        }
        // 需要选择“准考证登录”或“身份证号登录”或“手机号登录”的至少其中一项配置；
        if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_IDCARDLOGIN.getCode())) &&
                off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_ADMISSIONNUMLOGIN.getCode())) &&
                off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_PHONENUMLOGIN.getCode()))) {
            errMsgList.add("需要勾选【准考证登录】、【身份证号登录】、【手机号登录】的至少一项配置；");
        }

        // 是否开启视频回放
        boolean videoPlayBackFlag = on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOPLAYBACK.getCode()));
        if(videoPlayBackFlag) {
            if(!videoMonitorFlag) {
                errMsgList.add("开启'视频回放'，必须要开启'视频监控'；");
            }
            if(off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOPCPLAYBACK.getCode())) &&
                    off.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOAPPPLAYBACK.getCode()))) {
                errMsgList.add("开启'视频回放'，需要选择'PC视频回放'或'移动端视频回放'其中一项配置；");
            }
        }
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOPCPLAYBACK.getCode())) && !videoPlayBackFlag){
            errMsgList.add("勾选'PC端视频回放'，需要勾选'视频回放'配置项；");
        }
        // 勾选“移动端视频回放”需要勾选“双机位监控设置
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOAPPPLAYBACK.getCode()))) {
            if(!videoPlayBackFlag) {
                errMsgList.add("勾选'移动端视频回放'，需要勾选'视频回放'配置项；");
            } else if(!dualMonitorFlag){
                errMsgList.add("勾选'移动端视频回放'，需要勾选'双机位监控'配置项；");
            }
        }
        // 开启行为分析
        if(on.equals(taskKsConfigMap.get(TaskKsConfigCode.EXAM_CONFIG_CODE_VIDEOACTIONANALYSIS.getCode()))
                && !videoMonitorFlag) {
            errMsgList.add("开启'视频行为分析'，必须要开启'视频监控'；");
        }
        if(dualMonitorFlag && !videoMonitorFlag) {
            errMsgList.add("开启'双机位监控'，必须要开启'视频监控'；");
        }
        // ===== 视频监控 ==end===

        if (errMsgList != null && !errMsgList.isEmpty()) {
            //30006,错误编码已经和前端约定好，如果要修改只能前后端同时修改。
            throw new KqException(ResponseCode.VALID_ONLINE_TASK_CONFIG_ERROR.getCode(), "任务参数校验失败。",errMsgList);
        }

    }

    @Override
    public TaskKsConfig updateTranslateOpen(String taskId) {

        TaskKsConfig taskKsConfig = this.lambdaQuery()
                .eq(TaskKsConfig::getTaskId,taskId)
                .eq(TaskKsConfig::getConfigCode,"translate")
                .eq(TaskKsConfig::getDelFlag,false)
                .last("limit 1")
                .one();

        if (taskKsConfig == null) {
            throw new KqException(ResponseCode.ERROR_UNIFIED_TRANSLATE_VALUE.getCode(), ResponseCode.ERROR_UNIFIED_TRANSLATE_VALUE.getMsg());
        }

        String configValue = "false";
        if (taskKsConfig.getConfigValue().equals(configValue)) {
            configValue = "true";
        }

        this.lambdaUpdate()
                .eq(TaskKsConfig::getId,taskKsConfig.getId())
                .set(TaskKsConfig::getConfigValue,configValue)
                .update();

        taskKsConfig = this.lambdaQuery()
                .eq(TaskKsConfig::getTaskId,taskId)
                .eq(TaskKsConfig::getConfigCode,"translate")
                .eq(TaskKsConfig::getDelFlag,false)
                .last("limit 1")
                .one();

        return taskKsConfig;
    }
}
